import { singleton } from "../model/BaseModel";
import GlobalEvent from "../global/GlobalEvent";
import MainScreen from "../module/MainScreen";

export default class MatterManager extends Laya.EventDispatcher {
    @singleton
    public static readonly instance: MatterManager;

    public matter: any = Laya.Browser.window.Matter;
    public engine: any;

    bodies = [];


    sprite: Laya.Sprite;

    constructor() {
        super();
        // this.init();
    }


    public init(sprite: Laya.Sprite): void {
        this.engine = this.matter.Engine.create({
            positionIterations: 8,
            velocityIterations: 8,
            enableSleeping: false
        });
        this.engine.world.gravity.y = 0;
        this.matter.Engine.run(this.engine);

        this.matter.Events.on(this.engine, 'collisionStart', this.onCollisionStart.bind(this));

        // this.test();
        if (sprite) {
            let sp = new Laya.Sprite();
            sprite.addChild(sp);
            this.sprite = sp;
        }
        Laya.timer.frameLoop(1, this, () => {
            if (this.sprite) {
                this.writeFrame();
            }
        })
    }

    public writeFrame() {
        this.sprite.graphics.clear();
        for (const body of this.bodies) {

            if (body.parts.length > 1) {
                for (const part of body.parts) {
                    for (let i = 1; i < part.vertices.length; i++) {
                        let prePoint = part.vertices[i - 1];
                        let point = part.vertices[i];
                        this.sprite.graphics.drawLine(prePoint.x, prePoint.y, point.x, point.y, "#ff0000", 1);
                    }                    
                }
                
            } else {
                for (let i = 1; i < body.vertices.length; i++) {
                    let prePoint = body.vertices[i - 1];
                    let point = body.vertices[i];
                    this.sprite.graphics.drawLine(prePoint.x, prePoint.y, point.x, point.y, "#ff0000", 1);
                }
            }

        }
    }

    private onCollisionStart(event) {

        console.log('collllllllllllllll')

        GlobalEvent.instance.event("matter_collision_start", event);

    }

    public test() {

        this.engine.world.gravity.y = 0;
        let body1 = this.matter.Bodies.rectangle(300, 300, 100, 100, {
            isStatic: false,
            friction: 0,
            frictionStatic: 0,
            frictionAir: 0.1
        });
        this.addToWorld(body1)
    }


    public addToWorld(body) {
        this.matter.World.add(this.engine.world, body);
        this.bodies.push(body);
    }

    public setVelocity(body, speedX, speedY) {
        this.matter.Body.setVelocity(body, {
            x: speedX,
            y: speedY
        });
    }


    public setAngle(body, angle) {
        this.matter.Body.setAngle(body, angle);
    }

    public setPosition(body, x, y) {
        this.matter.Body.setPosition(body, {
            x: x,
            y: y
        });
    }

    public translate(body, x, y) {
        this.matter.Body.translate(body, {
            x, y
        });
    }

    public setScale(body, scale, point = null) {
        if (body) {
            this.matter.Body.scale(body, scale, scale, point);            
        }
    }


    public setScaleToSize(body, originSize, targetSize, point = null) {
        let scale = targetSize / originSize;
        this.setScale(body, scale, point);
    }

    public bodyCreate(options) {
        return this.matter.Body.create(options);
    }


    constraintCreate(options) {
        return this.matter.Constraint.create(options);
    }

    setAngularVelocity(body, velocity) {
        this.matter.Body.setAngularVelocity(body, velocity);
    }


    compositeRemove(composite, body) {
        composite.bodies = composite.parts;
        composite.parent = null;
        this.matter.Composite.remove(composite, body, )
    }

    compositeAdd(composite, body) {
        composite.bodies = composite.parts;
        composite.parent = null;
        this.matter.Composite.add(composite, body);
    }

    removeFromWorld(body) {
        this.matter.World.remove(this.engine.world, body);
        let index = this.bodies.indexOf(body);
        if (index >= 0) {
            this.bodies.splice(index, 1);
        }
    }

    removeAllBody() {
        this.matter.World.clear(this.engine.world);
        this.bodies = [];
    }
}